package com.specter.mvc.model.dao;

import java.io.Serializable;
import java.util.List;

import com.specter.mvc.model.Page;
import com.specter.mvc.model.Request;

/**
 * 使用自动注入生成配置文件的方式完成数据库操作，自动生成的配置文件规则如下：<br/>
 * 文件 namespace="Entity.class.name"；<br/>
 * 映射 resultMap="_Entity_RM"；<br/>
 * 排序 &lt;include refid="_orders" /&gt；<br/>
 * 分页查询时不用配置分页语句（ROWNUM,LIMIT,TOP 等），内部机制自动完成！
 * 
 * <p style="color:red;">
 * 由于内部机制使用下划线'_'的命名方式，自主命名勿用
 * </p>
 * 
 * @author Liang.Wang
 * @version 2017-03-01
 * 
 */
public interface BaseDao {

	/**
	 * 使用Spring中template进行数据库操作，<b>不建议使用</b><br/>
	 * 
	 * Mybatis 中返回：SqlSessionTemplate <br/>
	 * Hibernate 中返回：HibernateTemplate <br/>
	 * 
	 * 基础操作之外的操作可以使用，请注意按照上面进行 <b>强制转换</b>。
	 * 
	 * 
	 * @return 数据库操作模板
	 */
	public Object template();

	/**
	 * 直接SQL语句执行，<b>不建议使用</b><br/>
	 * 
	 * @param sql    执行的SQL语句
	 * @param params 预备语句中的值，对应顺序
	 * @return 执行结果（INSERT/UPDATE返回int, SELECT返回Map列表）
	 */
	public <T> T sql(String sql, Object... params);

	/**
	 * 自定义执行INSERT语句
	 * 
	 * @param stmt SQL语句ID
	 * @return 是否成功
	 */
	public default boolean insert(String stmt) {
		return this.insert(null, stmt, null);
	}

	/**
	 * 自定义执行INSERT语句
	 * 
	 * @param stmt   SQL语句ID
	 * @param params 执行参数
	 * @return 是否成功
	 */
	public default boolean insert(String stmt, Object params) {
		return this.insert(null, stmt, params);
	}

	/**
	 * 自定义执行INSERT语句
	 * 
	 * @param clazz  实体类型
	 * @param stmt   SQL语句ID
	 * @param params 执行参数
	 * @return 是否成功
	 */
	public boolean insert(Class<?> clazz, String stmt, Object params);

	/**
	 * 插入新数据，entity会被赋值新主键
	 * 
	 * @param entity 赋值的实体
	 * @return 是否成功
	 */
	public <T> boolean insert(T entity);

	/**
	 * 批量插入，默认批量为50条
	 * 
	 * @param entities 批量赋值的实体
	 * @return 是否成功
	 */
	public default boolean insertBatch(List<?> entities) {
		return insertBatch(entities, 50);
	}

	/**
	 * 批量指定步长插入
	 * 
	 * @param entities 批量赋值的实体
	 * @param size     批量步长
	 * @return 是否成功
	 */
	public boolean insertBatch(List<?> entities, int size);

	/**
	 * 批量插入，默认批量为50条
	 * 
	 * @param stmt   SQL语句ID
	 * @param params List对象
	 * @return 是否成功
	 */
	public default boolean insertBatch(String stmt, List<?> params) {
		return insertBatch(stmt, params, 50);
	}

	/**
	 * 批量指定步长插入
	 * 
	 * @param stmt   SQL语句ID
	 * @param params List对象
	 * @param size   批量步长
	 * @return 是否成功
	 */
	public boolean insertBatch(String stmt, List<?> params, int size);

	/**
	 * 插入或修改（根据ID是否为空），entity会被赋值新主键
	 * 
	 * @param entity 赋值的实体
	 * @return 是否成功
	 */
	public <T> boolean insertOrUpdate(T entity);

	/**
	 * 批量插入或修改（根据ID是否为空），批量长度为30
	 * 
	 * @param entities 批量赋值的实体
	 * @return 是否成功
	 */
	public boolean insertOrUpdate(List<?> entities);

	/**
	 * 批量指定步长插入或修改（根据ID是否为空）
	 * 
	 * @param entities 批量赋值的实体
	 * @param size     批量长度
	 * @return 是否成功
	 */
	public boolean insertOrUpdate(List<?> entities, int size);

	/**
	 * 自定义执行DELETE语句
	 * 
	 * @param stmt SQL语句ID
	 * @return 是否成功
	 */
	public default boolean delete(String stmt) {
		return this.insert(null, stmt, null);
	}

	/**
	 * 自定义执行DELETE语句
	 * 
	 * @param stmt   SQL语句ID
	 * @param params 执行参数
	 * @return 是否成功
	 */
	public default boolean delete(String stmt, Object params) {
		return this.insert(null, stmt, params);
	}

	/**
	 * 自定义执行DELETE语句
	 * 
	 * @param clazz  实体类型
	 * @param stmt   SQL语句ID
	 * @param params 执行参数
	 * @return 是否成功
	 */
	public boolean delete(Class<?> clazz, String stmt, Object params);

	/**
	 * 通过实体键值相等条件 删除
	 * 
	 * @param entity 赋值的实体
	 * @return 是否成功
	 */
	public <T> boolean delete(T entity);

	/**
	 * 通过ID删除
	 * 
	 * @param clazz 数据表对应的实体
	 * @param id    主键ID
	 * @return 是否成功
	 */
	public boolean deleteById(Class<?> clazz, Serializable id);

	/**
	 * 根据批量ID删除
	 * 
	 * @param clazz 数据表对应的实体
	 * @param ids   主键列表
	 * @return 是否成功
	 */
	public boolean deleteById(Class<?> clazz, List<? extends Serializable> ids);

	/**
	 * 自定义执行UPDATE语句
	 * 
	 * @param stmt SQL语句ID
	 * @return 是否成功
	 */
	public default boolean update(String stmt) {
		return this.update(null, stmt, null);
	}

	/**
	 * 自定义执行UPDATE语句
	 * 
	 * @param stmt   SQL语句ID
	 * @param params 执行参数
	 * @return 是否成功
	 */
	public default boolean update(String stmt, Object params) {
		return this.update(null, stmt, params);
	}

	/**
	 * 自定义执行UPDATE语句
	 * 
	 * @param clazz  实体类型
	 * @param stmt   SQL语句ID
	 * @param params 执行参数
	 * @return 是否成功
	 */
	public boolean update(Class<?> clazz, String stmt, Object params);

	/**
	 * 通过ID更新，ID不能为空
	 * 
	 * @param entity  赋值的实体
	 * @param isBlank 是否使用NULL值
	 * @return 是否成功
	 */
	public <T> boolean update(T entity);

	/**
	 * 通过ID更新，ID不能为空
	 * 
	 * @param entity  赋值的实体
	 * @param isBlank 是否使用NULL值
	 * @return 是否成功
	 */
	public <T> boolean update(T entity, boolean isBlank);

	/**
	 * 根据ID 批量更新，ID不能为空
	 * 
	 * @param entities 批量赋值的实体
	 * @param isBlank  是否使用NULL值
	 * @return 是否成功
	 */
	public <T> boolean update(List<T> entities);

	/**
	 * 根据ID 批量更新，ID不能为空
	 * 
	 * @param entities 批量赋值的实体
	 * @param isBlank  是否使用NULL值
	 * @return 是否成功
	 */
	public <T> boolean update(List<T> entities, boolean isBlank);

	/**
	 * 根据ID 更新指定属性值对
	 * 
	 * @param clazz  数据表对应的实体
	 * @param id     对应的主键ID
	 * @param params 属性,赋值（可为多对）
	 * @return 是否成功
	 */
	public boolean updateById(Class<?> clazz, Serializable id, Object... params);

	/**
	 * 批量更新，默认批量为100条
	 * 
	 * @param stmt   SQL语句ID
	 * @param params List对象
	 * @return 是否成功
	 */
	public default boolean updateBatch(String stmt, List<?> params) {
		return updateBatch(stmt, params, 100);
	}

	/**
	 * 批量指定步长更新
	 * 
	 * @param stmt   SQL语句ID
	 * @param params List对象
	 * @param size   批量步长
	 * @return 是否成功
	 */
	public boolean updateBatch(String stmt, List<?> params, int size);

	/**
	 * 直接按照statement来查询唯一记录值（非唯一会报错）
	 * 
	 * @param stmt SQL语句ID
	 * @return 查询结果
	 */
	public default <T> T selectOne(String stmt) {
		return this.selectOne(null, stmt, null);
	}

	/**
	 * 直接按照statement来查询唯一记录值（非唯一会报错）
	 * 
	 * @param stmt   SQL语句ID
	 * @param params 参数值
	 * @return 查询结果
	 */
	public default <T> T selectOne(String stmt, Object params) {
		return this.selectOne(null, stmt, params);
	}

	/**
	 * 直接按照statement来查询唯一记录值（非唯一会报错）
	 * 
	 * @param clazz  数据表实体类
	 * @param stmt   SQL语句ID
	 * @param params 参数值
	 * @return 查询结果
	 */
	public <T> T selectOne(Class<T> clazz, String stmt, Object params);

	/**
	 * 根据 相等属性 查询单个对象（非唯一会报错）
	 * 
	 * @param entity 赋值的实体
	 * @return 单个对象
	 */
	public <T> T selectOne(T entity);

	/**
	 * 根据 ID 查询（非唯一会报错）
	 * 
	 * @param clazz 数据表对应的实体
	 * @param id    主键ID
	 * @return 单个实体
	 */
	public <T> T selectOneById(Class<T> clazz, Serializable id);

	/**
	 * 按照属性值对来查询唯一结果（非唯一会报错）
	 * 
	 * @param clazz  数据表对应的实体
	 * @param params 属性,赋值（可为多对）
	 * @return 单个实体
	 */
	public <T> T selectOneByIt(Class<T> clazz, Object... params);

	/**
	 * 直接按照statement来查询<br/>
	 * 通过&lt;include refid="_orders" /&gt;构建排序
	 * 
	 * @param stmt SQL语句
	 * @return 查询结果
	 */
	public default <T> List<T> select(String stmt) {
		return this.select(null, stmt, null);
	}

	/**
	 * 直接按照statement来查询<br/>
	 * 通过&lt;include refid="_orders" /&gt;构建排序
	 * 
	 * @param stmt   SQL语句ID
	 * @param params 参数值，同时可以构建 orders_（已提供构建的工具类）
	 * @return 查询结果
	 */
	public default <T> List<T> select(String stmt, Object params) {
		return this.select(null, stmt, params);
	}

	/**
	 * 直接按照statement来查询<br/>
	 * 通过&lt;include refid="_orders" /&gt;构建排序
	 * 
	 * @param clazz  数据表实体类
	 * @param stmt   SQL语句ID
	 * @param params 参数值，同时可以构建 orders_（已提供构建的工具类）
	 * @return 查询结果
	 */
	public <T> List<T> select(Class<T> clazz, String stmt, Object params);

	/**
	 * 根据 相等属性 查询列表对象
	 * 
	 * @param entity 赋值的实体
	 * @param orders 排序字段，构建 orders_（已提供构建的工具类）
	 * @return 查询的列表
	 */
	public <T> List<T> select(T entity, Object orders);

	/**
	 * 查询（根据 列的映射条件）列表
	 * 
	 * @param clazz  数据表实体类
	 * @param params 列条件Map映射 可以为NULL
	 * @return 查询的列表
	 */
	public <T> List<T> select(Class<T> clazz, Object params);

	/**
	 * 查询（根据ID的IN批量查询）
	 * 
	 * @param clazz  数据表实体类
	 * @param ids    批量主键
	 * @param orders 排序字段<b style= "color:red">列名</b>以(COLUMN_NAME,ASC/DESC)的方式整理排序,
	 *               可以为NULL
	 * @return 结果列表
	 */
	public <T> List<T> selectById(Class<T> clazz, List<? extends Serializable> ids, Object orders);

	/**
	 * 按照属性值对来查询列表结果
	 * 
	 * @param clazz  数据表对应的实体
	 * @param params 属性,赋值（可为多对）
	 * @return 实体列表
	 */
	public <T> List<T> selectByIt(Class<T> clazz, Object... params);

	/**
	 * 按照自主条件 翻页查询，需要自己配置相应的SQL<br/>
	 * 通过&lt;include refid="_orders" /&gt;构建排序
	 * 
	 * @param stmt    对应SQL的statement（含 namespace 的全称）
	 * @param request 条件关系；同时可以构建结果排序；查询类型Request.QueryType
	 * @return 分页对象
	 */
	public default <T> Page<T> selectPage(String stmt, Request request) {
		return this.selectPage(null, stmt, request);
	}

	/**
	 * 按照自主条件 翻页查询，需要自己配置相应的SQL<br/>
	 * 通过&lt;include refid="_orders" /&gt;构建排序
	 * 
	 * @param clazz   数据表实体类
	 * @param stmt    对应SQL的statement（含 namespace 的全称）
	 * @param request 条件关系；同时可以构建结果排序；查询类型Request.QueryType
	 * @return 分页对象
	 */
	public <T> Page<T> selectPage(Class<T> clazz, String stmt, Request request);

	/**
	 * 按照属性的相等条件 '=' 翻页查询
	 * 
	 * @param clazz   对应表
	 * @param request 条件关系；同时可以构建结果排序；查询类型Request.QueryType
	 * @return 分页对象
	 */
	public <T> Page<T> selectPage(Class<T> clazz, Request request);
}
